/*
#
#  Copyright 2011 Matthew Jannace
#
#  This file is part of RoboCode BlackHoleAgent
#
#  RoboCode BlackHoleAgent is free software: you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation, either version 3 of the
#  License, or (at your option) any later version.
#
#  RoboCode BlackHoleAgent is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with RoboCode BlackHoleAgent. If not, see
#  <http://www.gnu.org/licenses/>.
#
 */
package com.jannaceltd.TeamBlackHoleBeer;

import com.jannaceltd.TeamBlackHoleBeer.Modules.Communication.Communication;
import com.jannaceltd.TeamBlackHoleBeer.Modules.CustomEvents.CustomEventProcessor;
import com.jannaceltd.TeamBlackHoleBeer.Modules.HelperClasses.Enemy;
import com.jannaceltd.TeamBlackHoleBeer.Modules.Targeting.Targeting;
import com.jannaceltd.TeamBlackHoleBeer.Modules.HelperClasses.TeamMate;
import com.jannaceltd.TeamBlackHoleBeer.Modules.Strategy.TeamStrategy;
import com.jannaceltd.TeamBlackHoleBeer.Modules.HelperClasses.VirtualBullets;
import com.jannaceltd.TeamBlackHoleBeer.Modules.Movement.Movement;
import com.jannaceltd.TeamBlackHoleBeer.Modules.Radar.Radar;
import com.jannaceltd.TeamBlackHoleBeer.Modules.Debug.Painting;
import com.jannaceltd.TeamBlackHoleBeer.Utilities.RobotStats;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.util.HashMap;
import robocode.BattleEndedEvent;
import robocode.BulletHitBulletEvent;
import robocode.BulletHitEvent;
import robocode.BulletMissedEvent;
import robocode.CustomEvent;
import robocode.DeathEvent;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.MessageEvent;
import robocode.RobotDeathEvent;
import robocode.RoundEndedEvent;
import robocode.ScannedRobotEvent;
import robocode.SkippedTurnEvent;
import robocode.WinEvent;

/**
 * Class extends the BlackHole_Abstract to create a BlackHole Agent
 * @author Matthew Jannace <mjannace@gmail.com>
 * @version 1.0
 */
public class BlackHoleAgent extends BlackHole_Abstract implements BlackHole_Interface {

    private RobotStats roboStats = null;
    protected boolean LoggingEnabled = false;
    //Windows
    //private String FilePath = "C:/Users/mjannace/Desktop/AgentLogs";
    //Unix
    private String FilePath = "/Users/mjannace/Desktop/AgentLogs";

    /**
     * Initializes Agent objects and setting
     */
    public void init() {

        enemies = new HashMap<String, Enemy>();
        teamates = new HashMap<String, TeamMate>();
        teamatesNextLocation = new HashMap<String, TeamMate>();
        friendlyFire = new HashMap<String, VirtualBullets>();
        myFire = new HashMap<String, VirtualBullets>();

        target = new Enemy();
        strategy = new TeamStrategy(this);
        move = new Movement(this);
        radar = new Radar(this);
        gun = new Targeting(this);
        comm = new Communication(this);

        EventProcessor = new CustomEventProcessor(this);
        paint = new Painting(this);
        roboStats = new RobotStats(this, FilePath);
        centerMass = new Point2D.Double((getBattleFieldWidth() / 2), (getBattleFieldHeight() / 2));
    }

    @Override
    public void run() {
        init();
        while (true) {
            radar.doRadarScan();
            strategy.ChooseTarget();
            gun.doShoot();
            move.doMove();
            comm.doBroadcastUpdate();
            execute();
        }
    }

    //--------------- Robot Custom Event Monitoring Event --------------------//
    @Override
    public void onCustomEvent(CustomEvent event) {
        EventProcessor.processEvents(event);
    }
    //--------------- Robot Communication Events -----------------------------//

    @Override
    public void onMessageReceived(MessageEvent event) {
        comm.doOnMessageReceived(event);
    }

    //--------------- Robot Debugging Events ---------------------------------//
    @Override
    public void onPaint(Graphics2D graphic) {
        paint.doPaint(graphic);
    }

    @Override
    public void onSkippedTurn(SkippedTurnEvent event) {
        System.out.println("ERROR: Our Turn Was Skipped!!!!!!!!!");
    }

    //--------------- Radar Events -------------------------------------------//
    @Override
    public void onScannedRobot(ScannedRobotEvent event) {
        radar.doOnScannedRobot(event);
    }

    @Override
    public void onRobotDeath(RobotDeathEvent event) {
        radar.doOnRobotDeath(event);
    }

    //--------------- Robot Gun Events ---------------------------------------//
    @Override
    public void onBulletHit(BulletHitEvent event) {
        gun.doRemoveMyFire(event.getBullet(), true);
    }

    @Override
    public void onBulletHitBullet(BulletHitBulletEvent event) {
        gun.doRemoveMyFire(event.getBullet(), false);
    }

    @Override
    public void onBulletMissed(BulletMissedEvent event) {
        gun.doRemoveMyFire(event.getBullet(), false);
    }

    //--------------- Robot Movement & Stats Logging Events ------------------//
    @Override
    public void onHitByBullet(HitByBulletEvent event) {
        roboStats.onHitByBullet(event);
    }

    @Override
    public void onHitRobot(HitRobotEvent event) {
        roboStats.onHitRobot(event);
        move.doEvasiveMove();
    }

    @Override
    public void onHitWall(HitWallEvent event) {
        roboStats.onHitWall(event);
        move.doEvasiveMove();
    }

    //--------------- Robot Stats & Logging Events ---------------------------//
    @Override
    public void onBattleEnded(BattleEndedEvent event) {
        if (LoggingEnabled) {
            roboStats.onBattleEnded(event);
        }
    }

    @Override
    public void onRoundEnded(RoundEndedEvent event) {
        if (LoggingEnabled) {
            roboStats.onRoundEnded(event);
        }
    }

    /**
     * This Method is called when the agent is killed
     * @param event
     */
    @Override
    public void onDeath(DeathEvent event) {
        if (LoggingEnabled) {
            roboStats.onDeath(event);
        }
    }

    /**
     * This Method is called when the agent Wins the Round
     * @param event
     */
    @Override
    public void onWin(WinEvent event) {
        if (LoggingEnabled) {
            roboStats.onWin(event);
        }
    }
}
